package loteria.servidor;

import java.util.Date;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

import loteria.Item;
import loteria.NumeroFueraDeRango;
import loteria.Observador;
import loteria.SorteoFinalizado;
import loteria.SorteoNoIniciado;
import loteria.SorteoPOA;
import loteria.dao.LoteriaDAO;
import loteria.dao.LoteriaDAOFactory;
import loteria.utils.Propiedades;

public class SorteoImpl extends SorteoPOA {

	private Set<Observador> clients = new HashSet<Observador>();
	private GenerarSorteo generarSorteo = null;
	Set<Item> sorteo = new HashSet<Item>();
	private LoteriaDAO dao = LoteriaDAOFactory.getInstance().getDAO(
			Propiedades.getValue("database"));

	@Override
	public int comprobar(int number) throws NumeroFueraDeRango,
			SorteoNoIniciado {
		// La expcion SorteoNoIniciado no se contempla porque el sorteo se
		// inicia cada vez que entra un nuevo Observador.

		Item item = null;
		if (number > GenerarSorteo.MAX_NUM)
			throw new NumeroFueraDeRango();
		item = dao.getItemByNumero(number);
		if (item != null)
			return item.premio;
		else {
			int total = 0 ;
			item = dao.getItemByPremio(GenerarSorteo.PRIMER_PREMIO);

			if (item != null) {
				if (Math.abs(item.numero - number) == 1)
					total += GenerarSorteo.ANT_POST_PRIMERO; 
				if (item.numero % 1000 == number % 1000)
					total += 1000;
			}
			item = dao.getItemByPremio(GenerarSorteo.SEGUNDO_PREMIO);
			if (item != null) {
				if (Math.abs(item.numero - number) == 1)
					total += GenerarSorteo.ANT_POST_SEGUNDO;
				if (item.numero % 1000 == number % 1000)
					total += 1000;
			}
			item = dao.getItemByPremio(GenerarSorteo.TERCER_PREMIO);
			if (item != null) {
				if (Math.abs(item.numero - number) == 1)
					total += GenerarSorteo.ANT_POST_TERCERO;
				if (item.numero % 1000 == number % 1000)
					total += 1000;
			}
			/** PREMIOS ESPECIALES RESTANTES
			 * 98 premios de 1.000 euros a la centena (tres últimas cifras) de los dos cuartos premios. - 0,23% (100 euros por décimo)
			 * 2.547 premios de 1.000 euros a todos los billetes cuyas 2 últimas cifras coincidan con los del primero, segundo o tercer premios. - 3,00% (100 euros por décimo)
			 * 8.499 reintegros (coincidencia de la última cifra del primer premio) de 200 euros. (premiando al portador el mismo valor de su participación) - 10% (20 euros por décimo) 
			 * */
			return total;

		}
		

	}

	@Override
	public void registrar(Observador observador) throws SorteoFinalizado {
		// La expcion SorteoFinalizado no se contempla porque el sorteo se
		// inicia cada vez que entra un nuevo Observador.
		System.out.println("\nSe registrar nuevo observador...");
		this.clients.add(observador);
		System.out.println("Nuevo observador registrado.");
		if ((generarSorteo == null) || (!generarSorteo.isAlive())) {
			generarSorteo = new GenerarSorteo();
			clients = new HashSet<Observador>();
			this.clients.add(observador);
			generarSorteo.start();

		}

	}

	private class GenerarSorteo extends Thread {

		// Limite de números en el sorteo
		public static final int MAX_NUM = 84999;
		private final int TIEMPO_INICIAL = Integer.parseInt(Propiedades
				.getValue("tiempo_inicial"));

		// Premios economicos
		private static final int PRIMER_PREMIO = 3000000;
		private static final int SEGUNDO_PREMIO = 1000000;
		private static final int TERCER_PREMIO = 500000;
		private static final int CUARTOS_PREMIOS = 2000000;
		private static final int QUITOS_PREMIOS = 50000;
		private static final int PEDREA = 1000;

		// Premios especiales
		private static final int ANT_POST_PRIMERO = 20000;
		private static final int ANT_POST_SEGUNDO = 12500;
		private static final int ANT_POST_TERCERO = 9600;

		// Cantidad de premios
		private int primer_premio = 1;
		private int segundo_premio = 1;
		private int tercer_premio = 1;
		private int cuartos_premios = 2;
		private int quintos_premios = 8;
		private int pedrea = 1774;

		public GenerarSorteo() {

		}

		@Override
		public void run() {
			System.out.println("\nIniciando sorteo en...");
			for (int i = TIEMPO_INICIAL; i > 0; i--) {
				System.out.print("" + i + "sg...");
				try {
					sleep(1000);
				} catch (InterruptedException e) {

					e.printStackTrace();
				}
			}
			int num_premios = primer_premio + segundo_premio + tercer_premio
					+ cuartos_premios + quintos_premios + pedrea;
			int i = 1;

			dao.reiniciarTablas();

			while (num_premios != 0) {

				int numero = generarNumAleatorio(MAX_NUM);

				Item existente = null;
				do {
					existente = dao.getItemByNumero(numero);
					if (existente != null)
						numero = generarNumAleatorio(MAX_NUM);

				} while (existente != null);

				Item item = new Item(numero, generarPremio());

				System.out.print("\nBola:" + i + " Número: " + item.numero
						+ " Premio: " + item.premio + "\n");

				dao.save(item);

				for (Observador client : clients) {
					client.actualizar(item);
				}
				try {
					if (item.premio > 1000)
						sleep(1000);
					else
						sleep(10);
				} catch (InterruptedException e) {

					e.printStackTrace();
				} finally {
					num_premios = primer_premio + segundo_premio
							+ tercer_premio + cuartos_premios + quintos_premios
							+ pedrea;
					i++;
				}

			}
			Item item = new Item(0, 0);
			for (Observador client : clients) {
				client.actualizar(item);
			}
			System.out.println("\nFin del sorteo");

		}

		private int generarNumAleatorio(int maximo) {

			Random r = new Random();
			int retorno;
			r.setSeed(new Date().getTime());
			do {
				retorno = r.nextInt(maximo);
			} while (retorno < 0);

			return retorno;
		}

		private int generarPremio() {

			boolean generado = false;
			int num_premios = primer_premio + segundo_premio + tercer_premio
					+ cuartos_premios + quintos_premios + pedrea;
			if (num_premios == 0)
				return 0;

			while (!generado) {
				int premio = generarNumAleatorio(20000);

				if ((premio >= 1) && (premio <= 25) && (primer_premio != 0)) {
					primer_premio--;
					generado = true;
					return PRIMER_PREMIO;
				} else if ((premio >= 26) && (premio <= 50)
						&& (segundo_premio != 0)) {
					segundo_premio--;
					generado = true;
					return SEGUNDO_PREMIO;
				} else if ((premio >= 51) && (premio <= 75)
						&& (tercer_premio != 0)) {
					tercer_premio--;
					generado = true;
					return TERCER_PREMIO;
				} else if ((premio >= 76) && (premio <= 125)
						&& (cuartos_premios != 0)) {
					cuartos_premios--;
					generado = true;
					return CUARTOS_PREMIOS;
				} else if ((premio >= 126) && (premio <= 226)
						&& (quintos_premios != 0)) {
					quintos_premios--;
					generado = true;
					return QUITOS_PREMIOS;
				}
				if (pedrea != 0) {
					pedrea--;
					generado = true;
					return PEDREA;

				}

			}

			return 0;

		}

	}
}
